import os
import uuid
import time
import datetime
from flask import Flask, render_template, request, redirect, url_for, send_file, abort, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads/'
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024  # 100MB限制
app.config['RETENTION_HOURS'] = 24
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev_key_for_temporary_file_sharing')

# 创建上传目录
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

limiter = Limiter(
    app=app,
    key_func=get_remote_address,
    default_limits=["5 per minute", "50 per hour"]
)

# 在内存中存储文件元数据
file_metadata = {}

class FileMetadata:
    def __init__(self, filename, expiration):
        self.filename = filename
        self.expiration = expiration
        self.download_count = 0

@app.route('/')
def index():
    """文件上传页面"""
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    """处理文件上传"""
    if 'file' not in request.files:
        return redirect(url_for('index'))
    
    file = request.files['file']
    if file.filename == '':
        return redirect(url_for('index'))
    
    # 生成唯一ID
    file_id = str(uuid.uuid4())
    save_path = os.path.join(app.config['UPLOAD_FOLDER'], file_id)
    
    # 保存文件
    file.save(save_path)
    
    # 计算过期时间（24小时）
    expiration_time = time.time() + app.config['RETENTION_HOURS'] * 3600
    
    # 存储元数据
    file_metadata[file_id] = FileMetadata(
        filename=file.filename,
        expiration=expiration_time
    )
    
    # 返回分享链接
    share_url = request.host_url + 'download/' + file_id
    return render_template('share.html', share_url=share_url, filename=file.filename)

@app.route('/download/<file_id>')
def download_page(file_id):
    """显示文件下载页面"""
    if file_id not in file_metadata:
        return render_template('error.html', error_message="文件不存在或已过期"), 404
    
    metadata = file_metadata[file_id]
    
    # 检查文件是否过期
    if time.time() > metadata.expiration:
        # 删除过期文件
        try:
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], file_id))
            del file_metadata[file_id]
        except:
            pass
        return render_template('error.html', error_message="文件已过期"), 410
    
    # 计算剩余时间
    remaining_seconds = metadata.expiration - time.time()
    remaining_hours = int(remaining_seconds / 3600)
    remaining_minutes = int((remaining_seconds % 3600) / 60)
    
    # 准备下载页面数据
    download_url = url_for('download_file_direct', file_id=file_id, _external=True)
    
    return render_template(
        'download.html',
        filename=metadata.filename,
        download_count=metadata.download_count,
        download_url=download_url,
        expiry_time=metadata.expiration
    )

@app.route('/download/direct/<file_id>')
def download_file_direct(file_id):
    """直接下载文件"""
    if file_id not in file_metadata:
        abort(404)
    
    metadata = file_metadata[file_id]
    
    # 检查文件是否过期
    if time.time() > metadata.expiration:
        # 删除过期文件
        try:
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], file_id))
            del file_metadata[file_id]
        except:
            pass
        abort(410)
    
    file_path = os.path.join(app.config['UPLOAD_FOLDER'], file_id)
    
    # 更新下载次数
    metadata.download_count += 1
    
    # 提供下载
    return send_file(
        file_path,
        as_attachment=True,
        download_name=metadata.filename
    )

@app.route('/api/file/<file_id>', methods=['GET'])
def get_file_info(file_id):
    """获取文件信息的API"""
    if file_id not in file_metadata:
        return jsonify({
            'status': 'error',
            'message': '文件不存在或已过期'
        }), 404
    
    metadata = file_metadata[file_id]
    
    # 检查文件是否过期
    if time.time() > metadata.expiration:
        # 删除过期文件
        try:
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], file_id))
            del file_metadata[file_id]
        except:
            pass
        return jsonify({
            'status': 'error',
            'message': '文件已过期'
        }), 410
    
    # 计算剩余时间
    remaining_seconds = metadata.expiration - time.time()
    remaining_hours = int(remaining_seconds / 3600)
    remaining_minutes = int((remaining_seconds % 3600) / 60)
    
    return jsonify({
        'status': 'success',
        'filename': metadata.filename,
        'download_count': metadata.download_count,
        'expiry_time': metadata.expiration,
        'remaining_time': {
            'hours': remaining_hours,
            'minutes': remaining_minutes,
            'seconds': int(remaining_seconds % 60)
        }
    })

# 新增API上传接口
# 在配置中添加API密钥
app.config['API_KEY'] = os.environ.get('API_KEY', 'default_secret_key_here')

# 修改API上传接口
@app.route('/api/upload', methods=['POST'])
def api_upload_file():
    # 检查API密钥
    api_key = request.headers.get('X-API-Key') or request.args.get('api_key')
    if api_key != app.config['API_KEY']:
        return jsonify({"error": "Invalid API key"}), 401
    
    if 'file' not in request.files:
        return jsonify({"error": "No file part"}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({"error": "No selected file"}), 400
    
    # 生成唯一ID
    file_id = str(uuid.uuid4())
    save_path = os.path.join(app.config['UPLOAD_FOLDER'], file_id)
    
    # 保存文件
    file.save(save_path)
    
    # 计算过期时间（24小时）
    expiration_time = time.time() + app.config['RETENTION_HOURS'] * 3600
    
    # 存储元数据
    file_metadata[file_id] = FileMetadata(
        filename=file.filename,
        expiration=expiration_time
    )
    
    # 返回JSON格式的下载地址
    download_url = request.host_url + 'download/' + file_id
    return jsonify({
        "download_url": download_url,
        "file_id": file_id,
        "expires_at": expiration_time
    })

def cleanup_expired_files():
    """清理过期文件的后台任务"""
    while True:
        time.sleep(3600)  # 每小时检查一次
        current_time = time.time()
        expired_files = []
        
        for file_id, metadata in file_metadata.items():
            if current_time > metadata.expiration:
                expired_files.append(file_id)
        
        for file_id in expired_files:
            try:
                os.remove(os.path.join(app.config['UPLOAD_FOLDER'], file_id))
                del file_metadata[file_id]
            except:
                pass
        
        print(f"{datetime.datetime.now()} - 清理了 {len(expired_files)} 个过期文件")

if __name__ == '__main__':
    # 启动清理线程
    import threading
    cleanup_thread = threading.Thread(target=cleanup_expired_files, daemon=True)
    cleanup_thread.start()
    
    app.run(host='0.0.0.0', port=5000)
